package com.chungkui.ratelimiter.impl;

import com.chungkui.check.core.bean.CheckResult;
import com.chungkui.check.exception.CheckFailException;
import com.chungkui.ratelimiter.RateLimiterCache;
import com.chungkui.ratelimiter.RateLimiterService;
import com.chungkui.ratelimiter.StandAloneRateLimiter;
import com.chungkui.ratelimiter.ValueResolve;
import com.chungkui.ratelimiter.anotation.RateLimiter;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;

public class StandAloneRatelimiterServiceImpl implements RateLimiterService {
    private final Logger log = LoggerFactory.getLogger(StandAloneRatelimiterServiceImpl.class);
    @Autowired
    RateLimiterCache rateLimiterCache;

    @Autowired
    ValueResolve valueResolve;

    private StandAloneRateLimiter buildRateLimiterService(String rate, Long warmPeriod, boolean blook, long waitLimit) {
        String realRate = valueResolve.resolve(rate);
        return new StandAloneRateLimiterImpl(Double.parseDouble(realRate), warmPeriod.equals(0L) ? null : warmPeriod,
                blook, waitLimit);
    }

    @Override
    public void limit(RateLimiter rateLimiter, String key) {
        StandAloneRateLimiter standAloneRateLimiter = rateLimiterCache.get(key);
        if (standAloneRateLimiter == null) {
            log.debug("流控规则初始化未完成直接放行并进行初始化！");
            rateLimiterCache.set(key,
                    buildRateLimiterService(rateLimiter.rate(),
                            rateLimiter.warmupPeriod(),
                            rateLimiter.block(),
                            rateLimiter.waitLimit()));
        } else if (!standAloneRateLimiter.check()) {
            throw new CheckFailException(rateLimiter.msg(), CheckResult.fail(rateLimiter.code(), rateLimiter.msg()));
        }
    }

    @Override
    public void limit(RateLimiter rateLimiter, String key, String dyParam) {
        String dynamic = key + ":" + dyParam;
        StandAloneRateLimiter dynamicStandAloneRateLimiter = rateLimiterCache.getDynamic(dynamic);
        StandAloneRateLimiter createStandAloneRateLimiter = null;
        if (StringUtils.isNotEmpty(rateLimiter.createRate())) {
            createStandAloneRateLimiter = rateLimiterCache.get(key);
            if (createStandAloneRateLimiter == null) {
                rateLimiterCache.set(key, buildRateLimiterService(rateLimiter.createRate(),
                        rateLimiter.warmupPeriod(),
                        rateLimiter.block(),
                        0L));
            }
        }
        if (dynamicStandAloneRateLimiter == null) {
            if (createStandAloneRateLimiter != null) {
                boolean createResult = createStandAloneRateLimiter.check();
                if (!createResult) {
                    throw new CheckFailException(rateLimiter.msg(), CheckResult.fail(rateLimiter.code(), rateLimiter.msg()));
                }
            }
            log.debug("流控规则初始化未完成直接放行并进行初始化！source:{}", key);
            rateLimiterCache.setDynamic(key, buildRateLimiterService(rateLimiter.rate(),
                    rateLimiter.warmupPeriod(),
                    rateLimiter.block(),
                    rateLimiter.waitLimit()));
        } else if (!dynamicStandAloneRateLimiter.check()) {
            throw new CheckFailException(rateLimiter.msg(), CheckResult.fail(rateLimiter.code(), rateLimiter.msg()));
        }
    }

}
